package com.sxhalo.fsms.quartz;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.sxhalo.fsms.domain.*;
import com.sxhalo.fsms.service.*;
import com.sxhalo.fsms.util.CacheUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sxhalo.fsms.util.DateUtil;

@DisallowConcurrentExecution //作业不并发
@Component
public class ScheduledSaveDataTask implements Job {

	@Autowired
	private RedisTemplate<String, ?> redisTemplate;
	
	ObjectMapper objectMapper = new ObjectMapper();
	


	@Autowired
	private ITransducerRunningStatusService  transducerRunningStatusService;
	@Autowired
	private ITransducerRunningDataService transducerRunningDataService;

	@Autowired
	private IDeviceEmRunningDataService emRunService;
	@Autowired
	private IMotorRunningDataService runService;
	@Autowired
	private IMotorReliabilityDataService relService;
	@Autowired
	private IFactDeviceService deviceService;
	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		// NULL不参与序列化
        objectMapper.setSerializationInclusion(Include.NON_NULL);

		System.out.println("SaveDataTask定时任务" + DateUtil.FormatTime(new Date()));
		
		//redis 连接失败 如何处理
		try {
			Long startTime = System.currentTimeMillis();
			
			//Set<String> keys = redisTemplate.keys("*");

			HashOperations<String, Object, Object> redis = redisTemplate.opsForHash();
			List<FactDevice> deviceTypes=getDevices();
			//马保数据
			List<RedisData> relList = new ArrayList<RedisData>();
			List<RedisData> runList = new ArrayList<RedisData>();
			//变频器数据
			List<RedisData> transducerRunningDataList = new ArrayList<RedisData>();
			List<RedisData> transducerRunningStatusesList = new ArrayList<RedisData>();

			//电能表
			List<RedisData> emDataList = new ArrayList<RedisData>();
			Date nowTime=new Date();
		 //	keys.remove("AlarmDevice");



			for (FactDevice device : deviceTypes) {
		        Map<Object, Object> rowData = redis.entries(device.getDeviceId()+"");

				if(rowData!=null&&rowData.size()>0){
					  RedisData data= JSON.parseObject(JSON.toJSONString(rowData),RedisData.class);

					 data.setDeviceId(device.getDeviceId());
                     data.setAcquisitionTime(nowTime);
					 //变频器
					 if(device.getDeviceTypeId()==DeviceTypeEnum.TRANSDUCER.getIndex()){
						 //设备运行状态

						 //设备运行数据
						// TransducerRunningData runData = getTransducerRunningData(device.getDeviceId(), rowData);

					     RedisData oldData = CacheUtil.getredismap(device.getDeviceId().toString());
						 Boolean isEquals= data.equalsvfdRunningData(oldData);
						 if(oldData==null||!isEquals){
							 transducerRunningDataList.add(data);
						 }
						 getTransducerState(device.getDeviceId(), data,transducerRunningStatusesList);


						 if(oldData==null||!isEquals||!oldData.equalsTransducer(data)){
							 CacheUtil.putredismap(device.getDeviceId().toString(), data);
						 }
						 //电能表
					 }else if(device.getDeviceTypeId()==DeviceTypeEnum.WATT_HOUR.getIndex()){
						 //设备运行数据
						 RedisData oldData = CacheUtil.getredismap(device.getDeviceId().toString());
						 if(oldData==null||!data.equalsEm(oldData)){
						 	//过滤异常数据
                             Boolean isSave=true;
							 Field[] fields =  data.getClass().getFields();
							 for( int i = 69; i < fields.length; i++){
								 Field f = fields[i];
								 Object obj=f.get(data);
								 if(obj!=null&&(new Float(obj.toString())>new Float(50000)||new Float(obj.toString())<0)){
									 isSave=false;
								 	break;
								 }
							 }

							 if(isSave){
								 CacheUtil.putredismap(device.getDeviceId().toString(), data);
								 emDataList.add(data);
							 }

					 }

					 }else{
						 //设备维护数据
						 RedisData oldData = CacheUtil.getredismap(device.getDeviceId().toString());
						 Boolean isEquals=data.equalsmpRunningData(oldData);
					     if(oldData==null||!isEquals){
							 runList.add(data);
					     }
						 getReliabilityData(device.getDeviceId(), data,relList);

						 if(oldData==null||!isEquals||!oldData.equalsMotor(data)){
							 CacheUtil.putredismap(device.getDeviceId().toString(), data);
						 }

					 }


				}


			}

			//保存数据
			relService.saveOrUpdateRedisData(relList);
			runService.foreachInsert(runList);
			transducerRunningStatusService.saveOrUpdate(transducerRunningStatusesList);
			transducerRunningDataService.foreachInsert(transducerRunningDataList);
			emRunService.foreachInsert(emDataList);

			Long runTime = System.currentTimeMillis()-startTime;
			System.out.println(" - [SaveData用时, "+(runTime/1000)+"秒] -");
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(" ---- [redis没连上] ----");
		}
		
		RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		
	}

	private void getTransducerState(Integer deviceId,  RedisData rowData,List<RedisData> relList) {
//		TransducerRunningStatus relData = new TransducerRunningStatus();
//		relData.setRev(rowData.get("REV")==null?0:Integer.parseInt(rowData.get("REV").toString()));
//		relData.setOnline(rowData.get("Online")==null?0:Integer.parseInt(rowData.get("Online").toString()));
//		relData.setFwd(rowData.get("FWD")==null?0:Integer.parseInt(rowData.get("FWD").toString()));
//		relData.setPoff(rowData.get("POFF")==null?0:Integer.parseInt(rowData.get("POFF").toString()));
//		relData.setAlarm(rowData.get("Alarm")==null?0:Integer.parseInt(rowData.get("Alarm").toString()));
//		relData.setAlarmCode(rowData.get("AlarmCode")==null?0:Integer.parseInt(rowData.get("AlarmCode").toString()));
//		relData.setStop(rowData.get("STOP")==null?0:Integer.parseInt(rowData.get("STOP").toString()));
//
//		relData.setDeviceId(deviceId);
//		return relData;

		RedisData oldData = CacheUtil.getredismap(deviceId.toString());
		if (oldData == null||!oldData.equalsTransducer(rowData)) {
			rowData.setDeviceId(deviceId);
			relList.add(rowData);
		}
	}




	private TransducerRunningData getTransducerRunningData(Integer deviceId, Map<Object, Object> rowData) {
		TransducerRunningData runData = new TransducerRunningData();
		runData.setAcquisitionTime(new Date());
		runData.setDeviceId(deviceId);
		runData.setOperatingFrequency(rowData.get("OperatingFrequency")==null?null:new BigDecimal(rowData.get("OperatingFrequency").toString()));
		runData.setSetFrequency(rowData.get("SettingFrequency")==null?null:new BigDecimal(rowData.get("SettingFrequency").toString()));
		runData.setBusVoltage(rowData.get("BusVoltage")==null?null:new BigDecimal(rowData.get("BusVoltage").toString()));
		runData.setOutputVoltage(rowData.get("OutputVoltage")==null?null:new BigDecimal(rowData.get("OutputVoltage").toString()));
		runData.setOutputCurrent(rowData.get("OutputCurrent")==null?null:new BigDecimal(rowData.get("OutputCurrent").toString()));
		runData.setRotationalVelocity(rowData.get("RotationalVelocity")==null?null:Integer.parseInt(rowData.get("RotationalVelocity").toString()));
		runData.setOutputTorque(rowData.get("OutputTorque")==null?null:new Float(rowData.get("OutputTorque").toString()));
		runData.setOutputPower(rowData.get("OutputPower")==null?null:new Float(rowData.get("OutputPower").toString()));
		runData.setClosedLoopSet(rowData.get("ClosedLoopSetting")==null?null:new BigDecimal(rowData.get("ClosedLoopSetting").toString()));
		runData.setClosedLoopFeedback(rowData.get("ClosedLoopFeedback")==null?null:new BigDecimal(rowData.get("ClosedLoopFeedback").toString()));
		runData.setReadCurrentSegmentnum(rowData.get("ReadCurrentSegmentnum")==null?null:Integer.parseInt(rowData.get("ReadCurrentSegmentnum").toString()));
		runData.setExternalLengthValue(rowData.get("ExternalLengthValue")==null?null:Integer.parseInt(rowData.get("ExternalLengthValue").toString()));
		runData.setExternalCountValue(rowData.get("ExternalCountValue")==null?null:Integer.parseInt(rowData.get("ExternalCountValue").toString()));
		runData.setTorqueSetValue(rowData.get("TorqueSetValue")==null?null:Integer.parseInt(rowData.get("TorqueSetValue").toString()));

	   return runData;
	}




	private void getReliabilityData(Integer deviceId, RedisData rowData,List<RedisData> relList ) {

		RedisData oldData=  CacheUtil.getredismap(deviceId.toString());
		if(oldData==null||!oldData.equalsMotor(rowData)){
			rowData.setDeviceId(deviceId);
			relList.add(rowData);
		}

//		MotorReliabilityData relData = new MotorReliabilityData();
//		relData.setAcquisitionTime(new Date());
//		relData.setDeviceId(deviceId);
//		relData.setCurrentRuningHour(rowData.getCurrentRuningHour());
//		relData.setTotalRuningHour(rowData.getTotalRuningHour());
//		relData.setTotalStart(rowData.getTotalStart());
//		relData.setTotalTrip(rowData.getTotalTrip());
//		return relData;
	}

	private MotorRunningData getRunningData(Integer deviceId, Map<Object, Object> rowData) {
		MotorRunningData runData = new MotorRunningData();
		runData.setAcquisitionTime(new Date());
		runData.setDeviceId(deviceId);
		if (rowData.get("Ready") != null) runData.setReady(Integer.parseInt(rowData.get("Ready").toString()));
		if (rowData.get("Online") != null) runData.setOnline(Integer.parseInt(rowData.get("Online").toString()));
		if (rowData.get("Running") != null) runData.setRunning(Integer.parseInt(rowData.get("Running").toString()));
		if (rowData.get("Start") != null) runData.setStart(Integer.parseInt(rowData.get("Start").toString()));
		if (rowData.get("Alarm") != null) runData.setAlarm(Integer.parseInt(rowData.get("Alarm").toString()));
		if (rowData.get("AlarmCode") != null) runData.setAlarmCode(rowData.get("AlarmCode").toString());
		if (rowData.get("Trip") != null) runData.setTrip(Integer.parseInt(rowData.get("Trip").toString()));
		if (rowData.get("TripCode") != null) runData.setTripCode(rowData.get("TripCode").toString());
		if (rowData.get("StartARunning") != null) runData.setStartaRunningFlag(Integer.parseInt(rowData.get("StartARunning").toString()));
		if (rowData.get("StartBRunning") != null) runData.setStartbRunningFlag(Integer.parseInt(rowData.get("StartBRunning").toString()));
		if (rowData.get("PhaseACurrent") != null) runData.setPhaseaCurrent(new BigDecimal(rowData.get("PhaseACurrent").toString()));
		if (rowData.get("PhaseBCurrent") != null) runData.setPhasebCurrent(new BigDecimal(rowData.get("PhaseBCurrent").toString()));
		if (rowData.get("PhaseCCurrent") != null) runData.setPhasecCurrent(new BigDecimal(rowData.get("PhaseCCurrent").toString()));
		if (rowData.get("UabLineVoltage") != null) runData.setUabLineVoltage(new BigDecimal(rowData.get("UabLineVoltage").toString()));
		if (rowData.get("UbcLineVoltage") != null) runData.setUbcLineVoltage(new BigDecimal(rowData.get("UbcLineVoltage").toString()));
		if (rowData.get("UcaLineVoltage") != null) runData.setUcaLineVoltage(new BigDecimal(rowData.get("UcaLineVoltage").toString()));
		if (rowData.get("ActivePower") != null) runData.setActivePower(new BigDecimal(rowData.get("ActivePower").toString()));
		if (rowData.get("ReactivePower") != null) runData.setReactivePower(new BigDecimal(rowData.get("ReactivePower").toString()));
		if (rowData.get("ApparentPower") != null) runData.setApparentPower(new BigDecimal(rowData.get("ApparentPower").toString()));
		if (rowData.get("PowerFactor") != null) runData.setPowerFactor(new BigDecimal(rowData.get("PowerFactor").toString()));
		if (rowData.get("CurrentUnbalance") != null) runData.setCurrentUnbalance(new BigDecimal(rowData.get("CurrentUnbalance").toString()));
		if (rowData.get("HeatCapacityPercentage") != null) runData.setHeatCapacityPercentage(new BigDecimal(rowData.get("HeatCapacityPercentage").toString()));
		return runData;
	}


    //电流表
	private DeviceElectricRunningData getElectricData(Integer deviceId, Map<Object, Object> rowData) {
		DeviceElectricRunningData relData = new DeviceElectricRunningData();

		relData.setAcquisitionTime(new Date());
		relData.setDeviceId(deviceId);
		relData.setComposeTotalActiveEnergy(rowData.get("ComposeTotalActiveEnergy")==null?null:new BigDecimal(rowData.get("ComposeTotalActiveEnergy").toString()));
		relData.setForwardTotalActiveEnergy(rowData.get("ForwardTotalActiveEnergy")==null?null:new BigDecimal(rowData.get("ForwardTotalActiveEnergy").toString()));
		relData.setReverseTotalActiveEnergy(rowData.get("ReverseTotalActiveEnergy")==null?null:new BigDecimal(rowData.get("ReverseTotalActiveEnergy").toString()));
		return relData;
	}



	private 	List<FactDevice> getDevices(){
		List<FactDevice> deviceTypes=null;
		Object devices=CacheUtil.getObject("devices");
		if(devices==null){
			deviceTypes=deviceService.getTypeList("");
			CacheUtil.putObject("devices",deviceTypes);
		}else{
			deviceTypes=(List<FactDevice> )devices;
		}
		return  deviceTypes;
	}
}
